﻿using System;
using System.Collections.Generic;
using System.Linq;
using ClientOverflow.CommunicationServices.Data;
using ClientOverflow.DataObjects;
using Answer = ClientOverflow.DataTransferObjects.Answer;
using Question = ClientOverflow.DataTransferObjects.Question;
using User = ClientOverflow.DataTransferObjects.User;

namespace ClientOverflow.CommunicationServices
{
    /// <summary>
    /// ClientOverflowService is the implementation of IClientOverflowService. The service decouples
    /// the DTOs from the data objects, so the client side is familiar with one type of objects only and 
    /// the data layer know only the data objects.
    /// The service is based on WCF 
    /// </summary>
    public class ClientOverflowService : IClientOverflowService
    {
        static ClientOverflowService()
        {
            DataAccessInitializer.Initialize();
        }

        public void RegisterNewUser(User newUser)
        {
            var user = UsersFactory.CreateUser(newUser);
            user.Department.Save();
            user.Save();
        }

        public User GetUser(string email, string password)
        {
            return UsersFactory.GetUser(email, password);
        }

        public List<User> GetAllUsers()
        {
            return UsersFactory.GetUsers();
        }

        public void RegisterNewQuestion(Question question, User user)
        {
            var newQuestion = QuestionsFactory.CreateQuestion(question, user);
            newQuestion.Save();
        }

        public List<DataTransferObjects.Tag> GetAllTags()
        {
            return TagsFactory.GetAllTags().Select(tag => tag.ToDto()).ToList();
        }

        public List<Question> GetAllQuestions()
        {
            return QuestionsFactory.GetAllQuestions().ToList();
        }

        public void PostAnswer(Question question, Answer newAnswer, User user)
        {
            var dbQuestion = QuestionsFactory.FindQuestion(question);
            var dbAnswer = AnswersFactory.CreateAnswer(newAnswer);
            var dbUser = UsersFactory.GetUser(user);
            dbQuestion.Answers.Add(dbAnswer);
            dbAnswer.User = dbUser;
            dbAnswer.Save();
            dbQuestion.Save();
        }

        public void ChooseAnswer(Question question, Answer answer)
        {
            var dbQuestion = question.ToDataObject();
            dbQuestion.CorrectAnswerID = answer.ToDataObject().ID;
            dbQuestion.Save();
        }

        public void AddQuestionVoteUp(Question question, User voter)
        {
            var dbQuestion = QuestionsFactory.FindQuestion(question);
            var dbVoter = UsersFactory.GetUser(voter);

            var questionVoteUp = new QuestionUpVote(){Question = dbQuestion, Voter = dbVoter};
            questionVoteUp.Save();
            dbQuestion.UpVotes.Add(questionVoteUp);
            dbQuestion.Update();
        }
    
        public void AddQuestionVoteDown(Question question, User voter)
        {
            var dbQuestion = QuestionsFactory.FindQuestion(question);
            var dbVoter = UsersFactory.GetUser(voter);

            var questionVoteUp = new QuestionDownVote(){Question = dbQuestion, Voter = dbVoter};
            questionVoteUp.Save();
            dbQuestion.DownVotes.Add(questionVoteUp);
            dbQuestion.Update();
        }

        public void AddAnswerVoteUp(Answer answer, User voter)
        {
            var dbAnswer = AnswersFactory.FindAnswer(answer);
            var dbVoter = UsersFactory.GetUser(voter);

            var answerUpVote = new AnswerUpVote() { Answer = dbAnswer, Voter = dbVoter };
            answerUpVote.Save();
            dbAnswer.UpVotes.Add(answerUpVote);
            dbAnswer.Update();
        }

        public void AddAnswerVoteDown(Answer answer, User voter)
        {
            var dbAnswer = AnswersFactory.FindAnswer(answer);
            var dbVoter = UsersFactory.GetUser(voter);

            var answerDownVote = new AnswerDownVote() { Answer = dbAnswer, Voter = dbVoter };
            answerDownVote.Save();
            dbAnswer.DownVotes.Add(answerDownVote);
            dbAnswer.Update();
        }

        public Question GetQuestion(Answer answer)
        {
            return QuestionsFactory.FindQuestionByAnswer(answer);
        }

    }
}
